package net.vtstar.vtcloud.framework.system.api.util;

import com.google.common.collect.ImmutableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;
import java.util.Comparator;
import java.util.List;
import java.util.ServiceLoader;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * com.linecorp.armeria.common.Flags
 */
public final class Flags {

    private static final Logger logger = LoggerFactory.getLogger(Flags.class);

    private static final List<FlagsProvider> FLAGS_PROVIDERS=
            ImmutableList.copyOf(ServiceLoader.load(FlagsProvider.class, Flags.class.getClassLoader()))
                    .stream()
                    .sorted(Comparator.comparingInt(FlagsProvider::priority).reversed())
                    .toList();
    
    private static final Predicate<InetAddress> PREFERRED_IP_V4_ADDRESSES =
            getValue(FlagsProvider::preferredIpV4Addresses, "preferredIpV4Addresses");

    private Flags() {}

    public static Predicate<InetAddress> preferredIpV4Addresses() {
        return PREFERRED_IP_V4_ADDRESSES;
    }

    private static <T> T getValue(Function<FlagsProvider, T> method, String flagName) {
        return getValue(method, flagName, unused -> true);
    }

    private static <T> T getValue(Function<FlagsProvider, T> method,
                                  String flagName, Predicate<T> validator) {
        for (FlagsProvider provider : FLAGS_PROVIDERS) {
            try {
                final T value = method.apply(provider);
                if (value == null) {
                    continue;
                }
                if (!validator.test(value)) {
                    logger.warn("{}: {} ({}, validation failed)", flagName, value, provider.name());
                    continue;
                }
                logger.info("{}: {} ({})", flagName, value, provider.name());
                return value;
            } catch (Exception ex) {
                logger.warn("{}: ({}, {})", flagName, provider.name(), ex.getMessage());
            }
        }
        // Should never reach here because DefaultFlagsProvider always returns a normal value.
        throw new Error("no FlagsProvider");
    }
    
}
